package facilitator;

import java.io.IOException;
import java.util.List;

import core.CalculationException;
import core.DmuList;
import core.Optimization;
import core.Optimizer;
import core.PdmOptimization;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import util.Util;

public class SolutionProvider {

    private List<List<PdmOptimization>> transitions;
    public DmuList dmuList;
    private double[] absUrmWeights;
    private double[] relUrmWeights;

    public double[] getAbsUrmWeights() {
        return absUrmWeights;
    }

    public void setAbsUrmWeights(double[] absUrmWeights) {
        this.absUrmWeights = absUrmWeights;
        this.relUrmWeights = Tool.getRelWeights(absUrmWeights);
    }

    public double[] getRelUrmWeights() {
        return relUrmWeights;
    }

    public void setRelUrmWeights(double[] relUrmWeights) {
        this.relUrmWeights = relUrmWeights;
        this.absUrmWeights = Tool.getAbsWeights(relUrmWeights);
    }
    private List<Optimization> deaOptimizations;

    private int getIndexForAlpha(double alpha) {
        for (int i = 0; i < this.transitions.size(); i++) {
            if (transitions.get(i).get(0).getAlpha() == alpha) {
                return i;
            }
        }
        return -1;
    }

    public void calculatePdmTransitions(double[] relUrmWeights) {
        this.setRelUrmWeights(relUrmWeights);    //TODO umrechnen
        transitions.clear();
        try {
            for (Optimization deaOpt : this.deaOptimizations) {
                TransitionExplorer expl = new TransitionExplorer(deaOpt, absUrmWeights, new PdmOptimization(dmuList, deaOpt.getObjectiveDmu(), 0, absUrmWeights, deaOpt).getOptimizationDirections());
                List<PdmOptimization> currList = expl.getTransitionList();

                for (int i = 0; i < currList.size(); i++) {
                    int index = this.getIndexForAlpha(currList.get(i).getAlpha());
                    //Util.print(deaOpt.getObjectiveDmu() + " - " +currList.get(i).getAlpha() + " - " + currList.get(i).getProfileDistance());
                    if (index > -1) {
                        transitions.get(index).add(currList.get(i));
                    } else {
                        List<PdmOptimization> newList = new ArrayList<PdmOptimization>();
                        newList.add(currList.get(i));
                        transitions.add(newList);
                    }
                }
            }
            for (int i = 0; i < this.deaOptimizations.size(); i++) {
                Optimization deaOpt = this.deaOptimizations.get(i);
                for (List<PdmOptimization> alphaList : this.transitions) {
                    boolean add = true;
                    for (PdmOptimization opt : alphaList) {
                        if (opt.getObjectiveDmu() == deaOpt.getObjectiveDmu()) {
                            add = false;
                        }
                    }
                    if (add) {
                        PdmOptimization pdmOpt = new PdmOptimization(this.dmuList, i, alphaList.get(0).getAlpha(), this.absUrmWeights, new PdmOptimization(dmuList, i, 0, absUrmWeights, deaOpt).getOptimizationDirections());
                        Optimizer.calculatePdm(pdmOpt);
                        alphaList.add(pdmOpt);
                    }
                }
            }
        } catch (CalculationException e) {
            e.printStackTrace();
        }
        //sort list ascending alpha
        for (List<PdmOptimization> alphaList : this.transitions) {
            Collections.sort(alphaList, new Comparator<PdmOptimization>(){
            public int compare(PdmOptimization o1, PdmOptimization o2) {
                if(o1.getObjectiveDmu() > o2.getObjectiveDmu()){
                    return 1;
                }
                else{
                    return -1;
                }
            }
        });
        }
        
        Collections.sort(transitions, new Comparator<List<PdmOptimization>>(){
            public int compare(List<PdmOptimization> o1, List<PdmOptimization> o2) {
                if(o1.get(0).getAlpha() > o2.get(0).getAlpha()){
                    return 1;
                }
                else{
                    return -1;
                }
            }
        });

    }
    public List<List<PdmOptimization>> getTransitionList() {
        return transitions;
    }
    public List<PdmOptimization> getPdmOptimizations(List<Integer> dmus, int index){
        List<PdmOptimization> returner = new ArrayList<PdmOptimization>();
        List<PdmOptimization> ls = this.transitions.get(index);
        for(int i:dmus){
            returner.add(ls.get(i));
        }
        return returner;
    }
    public static double[] getRelWeights(double[] absWeights) {
        double[] relWeights = absWeights.clone();
        for (int i = 0; i < absWeights.length; i++) {
            relWeights[i] = absWeights[i] / absWeights[0];
        }
        return relWeights;
    }
    /*public PdmOptimization[] getPdmOptimizations(double alpha, double[] absUrmWeights){
    try{
    PdmOptimization pdmOpt = new PdmOptimization(this.dmuList, alpha, absUrmWeights, this.optimizationDirections);
    Optimizer.calculatePdm(pdmOpt);
    return pdmOpt;
    } catch (CalculationException e) {
    e.printStackTrace();
    }
    return null;
    }*/

    public static double[] getRelOutputWeights(Optimization opt) throws CalculationException {
        double[] out = new double[opt.getOptimizationWeights().length - opt.getDmuList().inputSize];
        for (int i = 0; i < out.length; i++) {
            out[i] = opt.getOptimizationWeights()[i] / opt.getOptimizationWeights()[0];
        }
        return out;
    }

    public void loadDemoData() throws NumberFormatException, IOException, CalculationException {
        this.dmuList = Util.LoadFile("PDM1.csv");
        this.setAbsUrmWeights(new double[]{21, 34, 11, 13, 15, 22, 32, 21});
        this.deaOptimizations = new ArrayList<Optimization>();
        for (int i = 0; i < this.dmuList.size(); i++) {
            Optimization deaOpt = new Optimization(this.dmuList, i);
            Optimizer.calculateDea(deaOpt);
            this.deaOptimizations.add(deaOpt);
        }
    }

    public SolutionProvider() {
        this.transitions = new ArrayList<List<PdmOptimization>>();
    }
}
